home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
PROGRAMR
/
TKERN091.ZIP
/
SRC
/
FORMATTR.C
next >
Wrap
Text File
|
1994-03-01
|
14KB
|
711 lines
/*
* This file forms part of "TKERN" - "Troy's Kernel for Windows".
*
* Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* __formattr does formatted output. It is here to serve all the printf
* type functions. They call __formatter with the address of a function
* that __formatter will call when it has a character, and a void pointer
* which is passwd to that function as the first argument. The character
* is passed as the second argument.
*
* This function can be safely placed in the DLL without sacrificing
* portability. It basically means that this module can be under GNU
* Library License without compromising any other programs using the
* stubs (which are freely redistributable and usable for any purpose
* whatsoever).
*
* Note that this also makes it trivial to design new printf type
* functions without resorting to sprintf on a large string.
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <float.h>
#include <math.h>
#define FLAG_SHOWSIGN 0x0001
#define FLAG_LEFT 0x0002
#define FLAG_ZEROES 0x0004
#define FLAG_BLANK 0x0008
#define FLAG_ALTERNATE 0x0010
#define FLAG_UPPER 0x0020
#define FLAG_EXPONENTIAL 0x0040
#define FLAG_MAYEXP 0x0080
#pragma warn -pls
static char buffer[1024];
#pragma argsused
static int
show_integer( int (*func)(void *a, char b),
void *func_arg,
char const *pch,
char cSign,
int nWidth,
int nPrec,
int nFlags)
{
char cFill = ((nFlags & FLAG_ZEROES) ? '0' : ' ');
int iLen;
int nChars = 0;
iLen = strlen(pch) + (cSign ? 1 : 0);
if (iLen > nWidth)
nWidth = iLen;
else if (nWidth > iLen &&
(!(nFlags & FLAG_LEFT) ||
(nFlags & FLAG_ZEROES)))
{
if (cFill == '0' && cSign)
{
(*func)(func_arg, cSign);
cSign = '\0';
iLen--;
nWidth--;
nChars++;
}
while (nWidth > iLen)
{
nWidth--;
nChars++;
(*func)(func_arg, cFill);
}
}
if (cSign)
{
(*func)(func_arg, cSign);
iLen--;
nWidth--;
nChars++;
}
while (iLen--)
{
nWidth--;
(*func)(func_arg, *pch++);
nChars++;
}
while (nWidth--)
{
(*func)(func_arg, ' ');
nChars++;
}
return nChars;
}
static int
show_long( int (*func)(void *a, char b),
void *func_arg,
long number,
int nWidth,
int nPrec,
int nFlags)
{
char *pch = buffer;
char cSign = '\0';
int nLen;
ltoa(number, buffer, 10);
if (*pch == '-')
{
cSign = '-';
pch++;
}
else if (nFlags & FLAG_SHOWSIGN)
{
cSign = '+';
}
else if (nFlags & FLAG_BLANK)
{
cSign = ' ';
}
return show_integer(func, func_arg, pch, cSign, nWidth, nPrec, nFlags);
}
static int
show_ulong( int (*func)(void *a, char b),
void *func_arg,
long number,
int nWidth,
int nPrec,
int nFlags)
{
ultoa(number, buffer, 10);
return show_integer(func, func_arg, buffer, '\0', nWidth, nPrec, nFlags);
}
static int
show_hex( int (*func)(void *a, char b),
void *func_arg,
long number,
int nWidth,
int nPrec,
int nFlags)
{
ultoa(number, buffer, 16);
if (nFlags & FLAG_UPPER)
strupr(buffer);
return show_integer(func, func_arg, buffer, '\0', nWidth, nPrec, nFlags);
}
static int
show_real( int (*func)(void *a, char b),
void *func_arg,
long double fValue,
int nWidth,
int nPrecision,
int nFlags,
int nDigits)
{
int aiDigits[LDBL_DIG + 1];
long double fMantissa;
int nExponent;
int nSign = 1;
int nVisible;
char achExponent[10];
int nWritten = 0;
int iLastDigit;
int *piStart;
char *pchStart;
int i;
if (fValue < 0)
{
nSign = -1;
fValue = -fValue;
}
if (fValue)
nExponent = floor(log10(fValue));
else
nExponent = 0;
fMantissa = fValue / pow(10, nExponent);
aiDigits[0] = 0;
for (i = 1; i <= nDigits; i++)
{
if (fMantissa < 0) /* Rounding error */
fMantissa = 0;
aiDigits[i] = floor(fMantissa);
fMantissa = (fMantissa - aiDigits[i]) * 10;
}
for (; i < nDigits; i++)
{
aiDigits[i] = 0;
}
if (nPrecision == -1)
nPrecision = 6;
if (nFlags & FLAG_MAYEXP &&
nExponent >= 0 &&
nExponent +
(nPrecision ? nPrecision + 2 : 1) +
((nSign == -1 || (nFlags & FLAG_SHOWSIGN)) ? 1 : 0) > nWidth)
nFlags |= FLAG_EXPONENTIAL;
if (nFlags & FLAG_EXPONENTIAL)
{
ltoa(nExponent, achExponent, 10);
nVisible = 1 + (nPrecision ? nPrecision + 2 : 1) + strlen(achExponent);
}
else
{
if (nExponent < 0)
{
nVisible = nPrecision ? nPrecision : 1;
}
else
{
nVisible = nExponent + (nPrecision ? nPrecision + 2 : 1);
}
}
if (nSign == -1 || nFlags & FLAG_SHOWSIGN)
nVisible++;
if (!(nFlags & FLAG_LEFT))
{
while (nVisible < nWidth--)
{
(*func)(func_arg, ' ');
nWritten++;
}
}
if ((nFlags & FLAG_EXPONENTIAL) || nExponent < nDigits)
{
if ((nFlags & FLAG_EXPONENTIAL) || (nExponent < 0))
{
iLastDigit = 1 + nPrecision;
}
else
{
iLastDigit = 1 + nExponent + nPrecision;
}
if (iLastDigit < nDigits &&
aiDigits[iLastDigit+1] >= 5)
{
while (aiDigits[iLastDigit] == 9)
aiDigits[iLastDigit--] = 0;
aiDigits[iLastDigit]++;
}
}
if (nSign == -1)
{
(*func)(func_arg, '-');
nWritten++;
}
else if (nFlags & FLAG_SHOWSIGN)
{
(*func)(func_arg, '+');
}
if (aiDigits[0])
{
nExponent++;
piStart = aiDigits;
}
else
{
piStart = aiDigits + 1;
}
if (nFlags & FLAG_EXPONENTIAL)
{
(*func)(func_arg, '0' + *piStart++);
nWritten++;
if (nPrecision)
{
if (nPrecision > nDigits - 1)
nPrecision = nDigits - 1;
(*func)(func_arg, '.');
nWritten++;
while(nPrecision--)
{
(*func)(func_arg, '0' + *piStart++);
nWritten++;
}
if (nFlags & FLAG_UPPER)
(*func)(func_arg, 'E');
else
(*func)(func_arg, 'e');
nWritten++;
for (pchStart = achExponent; *pchStart; pchStart++)
{
(*func)(func_arg, *pchStart);
nWritten++;
}
}
}
else
{
if (nExponent >= 0)
{
while (nExponent-- >= 0)
{
if (nDigits-- > 0)
(*func)(func_arg, '0' + *piStart++);
else
(*func)(func_arg, '0');
nWritten++;
}
if (nPrecision)
{
(*func)(func_arg, '.');
nWritten++;
}
}
else
{
(*func)(func_arg, '0');
if (nPrecision)
(*func)(func_arg, '.');
while (nExponent++ && nPrecision--)
{
(*func)(func_arg, '0');
nWritten++;
}
}
while (nPrecision-- > 0)
{
if (nDigits-- > 0)
(*func)(func_arg, '0 ' + *piStart++);
else
(*func)(func_arg, '0');
nWritten++;
}
}
if (nFlags & FLAG_LEFT)
{
while (nVisible < nWidth--)
{
(*func)(func_arg, ' ');
nWritten++;
}
}
return nWritten;
}
int far _export
__formatter( int (*func)(void *a, char b),
void *func_arg,
char const *format,
va_list arg)
{
int nChars = 0;
int nPrecision;
int nWidth;
int nLong;
long nIntValue;
int nFlags;
int nPad;
int nLen;
union
{
short nShort;
int nInt;
long nLong;
unsigned short nUShort;
unsigned int nUInt;
unsigned long nULong;
float fFloat;
double fDouble;
long double fLongDouble;
char cChar;
char *pchString;
void *pvPointer;
} Value;
while (*format)
{
if (*format == '%')
{
if (*++format == '%')